import javax.swing.text.Position;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

// 逻辑层
public class CheeseStragy {
    public static CheeseStragy instance = new CheeseStragy();
    int rows = 5;
    int cols = 3;
    private ArrayList<P> avaliablePostions = new ArrayList();
    private CheeseStragy(){}

    public Cheese[][] getCheeses() {
        return cheeses;
    }

    Cheese[][] cheeses = new Cheese[rows][cols];

    public P getP(CheeseBoard.Coordinate[][] c, int x_, int y_) {
        return null;
    }

    // 记录棋子点击范围 以及被选中状态
    static class Cheese {
        public Rectangle rect;
        public boolean selected;
        Role role;
        int y;
        int x;


        public Cheese(int y, int x, Role role) {
            this.y = y;
            this.x = x;
            this.role = role;
        }
    }

    enum Role {
        RED, BLACK, NONE;
    }

    public void initCheeses() {
        for (int y = 0; y < rows; y++) {
            if (y == 2) continue; // 因为第二层没有棋子
            for (int x = 0; x < cols; x++) {
                // 红棋和黑棋生成
                cheeses[y][x] = y < 2 ? new Cheese(y, x, Role.RED) : new Cheese(y, x, Role.BLACK);
                System.out.println(String.format("cheeses[%d][%d]",y,x));
            }
        }
    }

    // 判断越过的棋子
    static class P {
        int overY, overX = -1;
        int y, x;

        P(int y, int x) {
            this.y = y;
            this.x = x;
        }
        P(int y, int x, int overY, int overX) {
            this.y = y;
            this.x = x;
            this.overY = overY;
            this.overX = overX;
        }
        public String toString(){
            return "("+y+","+x+")";
        }
    }

    // 存储一个棋子越过的棋子
    HashMap<Cheese,ArrayList<P>> map = new HashMap<>();

    public Cheese getCheese(ArrayList<P> plist){
        for(Map.Entry<Cheese,ArrayList<P>> entry: map.entrySet()) {
            if (entry.getValue() == plist) return entry.getKey();
        }
        return null;
    }

    public ArrayList getAvaliablePostion() {
        return avaliablePostions;
    }


    /**
     * 找到棋子相邻的位置是否可落子
     *
     * @param cheese -棋子
     * @return 可落子的位置
     */
    ArrayList getAvaliablePostion(Cheese cheese) {
        avaliablePostions.clear();
        map.clear();
        int x = cheese.x, y = cheese.y;
        int tmp_x = 1;
        avaliablePostions = new ArrayList();
        //上
        handleUpDirect(cheese);
        //下
        handleDownDirect(cheese);

        // 左右两边只用至多判断隔一个的情况，因为一行只有三个棋子
        if (y != 2) {
            //左
            tmp_x = x - 1;
            if (isEmpty(y, tmp_x)) {
                // 如果左边的位置是空的，则是合法的位置
                avaliablePostions.add(new P(y, tmp_x));
            } else if (isOpponent(cheese, y, tmp_x)) {
                // 如果左边的左边位置是空的，而且左边是对手的棋子，也是合法的位置
                tmp_x = x - 2;
                if (isEmpty(y, tmp_x)) {
                    avaliablePostions.add(new P(y, tmp_x, y, x - 1));
                }
            }

            //右
            tmp_x = x + 1;
            if (isEmpty(y, tmp_x)) {
                // 右边和左边的判断逻辑一致
                avaliablePostions.add(new P(y, tmp_x));
            } else if (isOpponent(cheese, y, tmp_x)) {
                tmp_x = x + 2;
                if (isEmpty(y, tmp_x)) {
                    avaliablePostions.add(new P(y, tmp_x, y, x + 1));

                }
            }
        }
        map.put(cheese, avaliablePostions);
        System.out.println(avaliablePostions);
        return avaliablePostions;
    }

    private void handleUpDirect(Cheese cheese) {
        int x = cheese.x, y = cheese.y;
        int x2 = -1;
        int[] x1 = new int[]{-1, -1, -1};
        int y1 = (cheese.role == Role.RED) ? y + 1 : y - 1; //黑棋和红棋往上的方向不一样 
        // 红棋走到底 黑棋走到顶 说明原先不是在沙漏的中间点 而且没有往沙漏中间点走
        if ((cheese.role == Role.RED && y1 == 4) || (cheese.role == Role.BLACK && y1 == 0)) {
            // 则只能有x坐标相同这一种情况
            x1 = new int[]{x, -1, -1};
        } 
        // 原先在沙漏的中间点
        else if ((cheese.role == Role.RED && y1 == 3) || (cheese.role == Role.BLACK && y1 == 1)) {
            // 落子x坐标有三种情况
            x1 = new int[]{0, 1, 2};
        } 
        // 原先在沙漏中间点的上面或下面一行
        else if (y1 == 2){
            // 落子的x坐标确定为1
            x1 = new int[]{1, -1, -1};
        } 
        // 从底部或者顶部走到第一行和第三行
        else if (((cheese.role == Role.RED && y1 == 1) || (cheese.role == Role.BLACK && y1 == 3))) {
            // 落子的x坐标只能和原先相同
            x1 = new int[]{x, -1, -1};
        }
        for(int index = 0; index < x1.length && x1[index] != -1; index++) {
            // 如果落点为空
            if (isEmpty(y1, x1[index])) {
                avaliablePostions.add(new P(y1, x1[index]));
            }
            // 如果落点为对方的棋子
            else if (isOpponent(cheese, y1, x1[index])) { 
                // 判断是否可以连跳
                int y2 = (cheese.role == Role.RED) ? y1 + 1 : y1 - 1;
                if ((cheese.role == Role.RED && y2 == 3) || (cheese.role == Role.BLACK && y2 == 1)) {
                    // 斜着跳了两次
                    if (x == 0) {
                        x2 = 2;
                    } 
                    // 竖着跳了两次
                    else if (x == 1) {
                        x2 = 1;
                    } 
                    // 斜着跳了两次
                    else if (x == 2) {
                        x2 = 0;
                    }
                }
                // 最后一次是竖着跳的 
                else if ((cheese.role == Role.RED && y2 == 4) || (cheese.role == Role.BLACK && y2 == 0)) {
                    x2 = x1[index];
                } 
                // 最后一次跳到了沙漏的中间
                else if (y2 == 2) {
                    x2 = 1;
                }
                if (isEmpty(y2, x2)) {
                    avaliablePostions.add(new P(y2, x2, y1, x1[index]));
                }
            }
        }
    }

    private void handleDownDirect(Cheese cheese) {
        int x = cheese.x, y = cheese.y;
        int x2 = -1;
        int[] x1 = new int[]{-1, -1, -1};
        int y1 = (cheese.role == Role.RED) ? y - 1 : y + 1;
        if ((cheese.role == Role.RED && y1 == 3) || (cheese.role == Role.BLACK && y1 == 1)) {
            x1 = new int[]{x, -1, -1};
        } else if (y1 == 2){
            x1 = new int[]{1, -1, -1};
        } else if (((cheese.role == Role.RED && y1 == 1) || (cheese.role == Role.BLACK && y1 == 3))) {
            x1 = new int[]{0, 1, 2};
        }
        for(int index = 0; index < x1.length && x1[index] != -1; index++) {
            if (isOpponent(cheese, y1, x1[index])) { //为对方的棋子
                int y2 = (cheese.role == Role.RED) ? y1 - 1 : y1 + 1;
                if ((cheese.role == Role.RED && y2 == 1) || (cheese.role == Role.BLACK && y2 == 3)) {
                    if (x == 0) {
                        x2 = 2;
                    } else if (x == 1) {
                        x2 = 1;
                    } else if (x == 2) {
                        x2 = 0;
                    }
                } else if ((cheese.role == Role.RED && y2 == 0) || (cheese.role == Role.BLACK && y2 == 4)) {
                    x2 = x1[index];
                } else if (y2 == 2) {
                    x2 = 1;
                }
                if (isEmpty(y2, x2)) {
                    avaliablePostions.add(new P(y2, x2, y1, x1[index]));
                }
            }
        }
    }

    /**
     * 根据当前的棋子判断指定位置的棋子是否为对手的棋子
     *
     * @param cheese
     * @param x
     * @param y
     */
    private boolean isOpponent(Cheese cheese, int y, int x) {
        if (0 <= y && y < rows && 0 <= x && x < cols) {
            return cheeses[y][x] != null && cheeses[y][x].role != cheese.role;
        }
        return false;
    }

    /**
     * 指定的位置是否是空位
     *
     * @param x
     * @param y
     * @return
     */
    boolean isEmpty(int y, int x) {
        if (0 <= y && y < rows && 0 <= x && x < cols) {
            return cheeses[y][x] == null;
        }
        return false;
    }

    /**
     * 落子
     * @param cheese
     * @param p
     * @return
     */
    public void goTargetPosition(Cheese cheese, P p, CheeseBoard.Coordinate[][] c) {
        for(P pos : avaliablePostions) {
            if(pos.y == p.y && pos.x == p.x) {
                cheeses[cheese.y][cheese.x] = null;
                cheese.y = p.y;
                cheese.x = p.x;
                cheeses[p.y][p.x] = cheese;
                setCheeseSelected(p.y, p.x);
                cheeses[p.y][p.x].rect = new Rectangle(c[p.y][p.x].x - 5, c[p.y][p.x].y - 5, 20, 20);
                //吃子
                if (pos.overY != -1 && pos.overX != -1){
                    cheeses[pos.overY][pos.overX] = null;
                }
                return;
            }
        }
    }

    public void setCheeseSelected(int y_, int x_){
        for (int y = 0; y < rows; y++) {
            for (int x = 0; x < cols; x++) {
               if ((y == y_ && x == x_) && cheeses[y][x] != null){
                   cheeses[y][x].selected = true;
               } else {
                   if (cheeses[y][x] != null)
                        cheeses[y][x].selected = false;
               }
            }
        }
    }

    public static void main(String[] args) {
        CheeseStragy cs = new CheeseStragy();
        cs.initCheeses();
        Cheese cheese = new Cheese(1, 1, Role.RED);
        ArrayList result = cs.getAvaliablePostion(cheese);
//        boolean b = cs.goTargetPosition(cheese, new CheeseStragy.P(2,1));
        System.out.println(result);
    }
}